﻿#include "StepSettingDialog.h"
#include <QMenu>
#include <QMessageBox>
#include <QFileDialog>
#include "DataTrans.h"
#include "StepEditDialog.h"

using ParamInfo = stru_BTS_CMD_SET_STEP76_Ex::StepInfo::ParamInfo;

enum {
	COL_TIME = 2,
	COL_VOLT = 3,
	COL_CURRENT = 4,
};


//StepTableHelper
void StepTableHelper::init(QTableWidget *table)
{	
	tableWidget = table;

	QStringList strListHeader;
	strListHeader << tr("工步号") << tr("工步名称") << tr("时间(H:M:S:MS)") << tr("电压(V)") << tr("电流(A)") << tr("截止电流(A)") << tr("截止电压(V)");
	tableWidget->setColumnCount(strListHeader.size());
	tableWidget->setHorizontalHeaderLabels(strListHeader);

	tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); //单击选择一行  
	tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);  //设置只能选择一行，不能多行选		
	tableWidget->setEditTriggers(QTableWidget::NoEditTriggers);	
}

void StepTableHelper::updateTable(const BTEStepInfo &stepInfo)
{
	int prec = 2;

	const auto &stru_step = stepInfo.step;
	int step_count = stru_step.stepList.size();
	int item_count = tableWidget->columnCount();

	tableWidget->setRowCount(step_count);
	for (int row = 0; row < step_count; row++)
	{
		const auto &step = stru_step.stepList[row];

		QTableWidgetItem *tableItem[32] = {0};
		for (int i = 0; i < item_count; i++)
		{
			tableItem[i] = new QTableWidgetItem();
			if (row == step_count - 1) //停止
			{
				auto flag = tableItem[i]->flags();
				tableItem[i]->setFlags(flag & (~Qt::ItemIsSelectable));
			}
		}
		tableItem[0]->setText(QString::number(row + 1));
		tableItem[1]->setText(step.stepName());

		if (step.isTimeVaild())
			tableItem[2]->setText(DataTrans::fromTimeUnit(step.Time()));
		if (step.isVoltageVaild())
			tableItem[3]->setText(QString::number(step.Voltage(), 'f', prec));
		if (step.isCurrentVaild())
			tableItem[4]->setText(QString::number(step.Current(), 'f', prec));
		if (step.isStopCurrentVaild())
			tableItem[5]->setText(QString::number(step.StopCurrent(), 'f', prec));
		if (step.isStopVoltageVaild())
			tableItem[6]->setText(QString::number(step.StopVoltage(), 'f', prec));

		if (step.StepType == STEP_TYPE_LOOP)
		{
			tableItem[2]->setText(tr("起始:") + QString::number(step.BeginStepID()));
			tableItem[3]->setText(tr("次数:") + QString::number(step.CountLoop()));
		}

		for (int i = 0; i < item_count; i++)
			tableWidget->setItem(row, i, tableItem[i]);
	}
}


//
StepSettingDialog::StepSettingDialog(QWidget *parent)
	: QDialog(parent)
{
	ui.setupUi(this);		

	m_tableHelper.init(ui.tableWidget);
	
	ui.btnSet->setVisible(false);
	ui.btnBack->setVisible(false);
}

StepSettingDialog::~StepSettingDialog()
{
}

void StepSettingDialog::showEvent(QShowEvent *event)
{
	initStep();
	__super::showEvent(event);
}

void StepSettingDialog::stepParamToUi(const stru_BTS_CMD_SET_STEP76_Ex::StepInfo &step, int param_index, QCheckBox *box, QLineEdit *edit)
{
	if (step.paramList[param_index].vaild)
	{
		box->setChecked(true);
		if (param_index == PARAM_ProtectDelayTime
			|| param_index == PARAM_ProtectDetalVolTime)
		{		
			int var = (int)step.paramList[param_index].data.toULongLong() / 1000;
			edit->setText(QString::number(var));
		}
		else
		{
			double var = step.paramList[param_index].data.toDouble();
			edit->setText(QString::number(var, 'f', 4));			
		}
		edit->home(false);
	}
	else
	{
		box->setChecked(false);
		edit->clear();
	}
}

void StepSettingDialog::initStep()
{
	int prec = 4;

	ui.lineStartStep->setValue(stepInfo.startStepIndex);

	ui.lineUser->setText(stepInfo.creator);
	ui.lineCellNum->setText(stepInfo.cellBatch);
	ui.textMomo->setText(stepInfo.memo);

	auto step = stepInfo.step.stepList[0];
	if (step.isRecordTimeIntervalVaild())
	{
		ui.boxRecordTimeGap->setChecked(true);
		ui.lineRecordTimeGap->setValue((int)step.RecordTimeInterval() / 1000);
	}


	//电压下限
	stepParamToUi(step, PARAM_RecordVoltageChange, ui.boxRecordVoltGap, ui.lineRecordVoltGap);
	stepParamToUi(step, PARAM_RecordCurrentChange, ui.boxRecordCurrentGap, ui.lineRecordCurrentGap);

	stepParamToUi(step, PARAM_ProtectVoltageLower,ui.boxSecurityVoltLow,ui.lineSecurityVoltLow);
	stepParamToUi(step, PARAM_ProtectVoltageUpper, ui.boxSecurityVoltUp, ui.lineSecurityVoltUp);

	stepParamToUi(step, PARAM_ProtectCurrentLower, ui.boxSecurityCurrentLow, ui.lineSecurityCurrentLow);
	stepParamToUi(step, PARAM_ProtectCurrentUpper, ui.boxSecurityCurrentUp, ui.lineSecurityCurrentUp);

	stepParamToUi(step, PARAM_ProtectTempatureLower, ui.boxSecurityTempLow, ui.lineSecurityTempLow);
	stepParamToUi(step, PARAM_ProtectTempatureUpper, ui.boxSecurityTempUp, ui.lineSecurityTempUp);

	stepParamToUi(step, PARAM_ProtectDelayTime, ui.boxSecurityDelay, ui.lineSecurityDelay);
	
	stepParamToUi(step, PARAM_ProtectDetalVol, ui.boxProtectDetal, ui.lineProtectDetalVol);
	stepParamToUi(step, PARAM_ProtectDetalVolTime, ui.boxProtectDetal, ui.lineProtectDetalTime);

	updateTable();
}

bool StepSettingDialog::uiToStep()
{
	DeviceData *pDevice = g_project->deviceData(DeviceString);
	int scale = g_project->deviceData(DeviceString)->scale(itemIndex);
	stepInfo.startStepIndex = ui.lineStartStep->value();
	stepInfo.creator = ui.lineUser->text();
	stepInfo.cellBatch = ui.lineCellNum->text();	
	stepInfo.memo = ui.textMomo->toPlainText();

	double maxCurrent = pDevice->maxCurrent() * 1.1 * scale;
	double maxVoltage = pDevice->maxVoltage() * 1.1 * scale;
	double maxCapacity = pDevice->maxCapacity();
	double maxTemp = pDevice->maxTempature();
	double maxDelay = 100000;

	double recordVoltGap = 0;
	double recordCurrentGap = 0;
	double securityVoltLow = 0;
	double securityVoltUp = 0;
	double securityCurrentLow = 0;
	double securityCurrentUp = 0;
	double securityTempLow = 0;
	double securityTempUp = 0;
	double securityCapUp = 0;
	double securityDelay = 0;
	double protectDetalVolTime = 0;
	double protectDetalVol = 0;

	if (!checkParam(ui.boxRecordVoltGap, ui.lineRecordVoltGap, recordVoltGap, 0, 100000)
		|| !checkParam(ui.boxRecordCurrentGap, ui.lineRecordCurrentGap, recordCurrentGap, 0, 100000)
		|| !checkParam(ui.boxSecurityVoltLow, ui.lineSecurityVoltLow, securityVoltLow, 0, maxVoltage)
		|| !checkParam(ui.boxSecurityVoltUp, ui.lineSecurityVoltUp, securityVoltUp, securityVoltLow, maxVoltage)
		|| !checkParam(ui.boxSecurityCurrentLow, ui.lineSecurityCurrentLow, securityCurrentLow, 0, maxCurrent)
		|| !checkParam(ui.boxSecurityCurrentUp, ui.lineSecurityCurrentUp, securityCurrentUp, securityCurrentLow, maxCurrent)
		|| !checkParam(ui.boxSecurityTempLow, ui.lineSecurityTempLow, securityTempLow, 0, maxTemp)
		|| !checkParam(ui.boxSecurityTempUp, ui.lineSecurityTempUp, securityTempUp, securityTempLow, maxTemp)
		|| !checkParam(ui.boxSecurityDelay, ui.lineSecurityDelay, securityDelay, 0, maxDelay)
		|| !checkParam(ui.boxProtectDetal, ui.lineProtectDetalTime, protectDetalVolTime, 0, maxDelay, false)
		|| !checkParam(ui.boxProtectDetal, ui.lineProtectDetalVol, protectDetalVol, 0, maxDelay, false))
		return false;

	QVector<int> extParam;
	extParam << PARAM_RecordTimeInterval << PARAM_RecordVoltageChange << PARAM_RecordCurrentChange
		<< PARAM_ProtectVoltageLower << PARAM_ProtectVoltageUpper
		<< PARAM_ProtectCurrentLower << PARAM_ProtectCurrentUpper << PARAM_ProtectTempatureLower
		<< PARAM_ProtectTempatureUpper << PARAM_ProtectDelayTime
		<< PARAM_ProtectDetalVolTime << PARAM_ProtectDetalVol;

	auto &list = stepInfo.step.stepList;
	for (int i = 0; i < list.size(); i++)
	{
		auto &step = list[i];
		for (int j = 0; j < extParam.size(); j++)
			step.paramList[extParam[j]].clear();

		if (step.StepType == STEP_TYPE_STOP)
			continue;

		if (ui.boxRecordTimeGap->isChecked())
		{
			int sec = ui.lineRecordTimeGap->text().toInt();
			//结束和循环操作不需要			
			step.setRecordTimeInterval(OP_BIG_EQU, sec * 1000);
		}

		//电压间隔
		if (ui.boxRecordVoltGap->isChecked())
		{
			step.setRecordVoltageChange(OP_BIG_EQU, recordVoltGap);
		}

		//电流间隔
		if (ui.boxRecordCurrentGap->isChecked())
		{
			step.setRecordCurrentChange(OP_BIG_EQU, recordCurrentGap);
		}

		//电压下限
		if (ui.boxSecurityVoltLow->isChecked())
		{
			step.setProtectVoltageLower(OP_BIG_EQU, securityVoltLow);
		}
		//电压上限
		if (ui.boxSecurityVoltUp->isChecked())
		{
			step.setProtectVoltageUpper(OP_SMALL_EQU, securityVoltUp);
		}
		//电流下限
		if (ui.boxSecurityCurrentLow->isChecked())
		{
			step.setProtectCurrentLower(OP_BIG_EQU, securityCurrentLow);
		}
		//电流上限
		if (ui.boxSecurityCurrentUp->isChecked())
		{
			step.setProtectCurrentUpper(OP_SMALL_EQU, securityCurrentUp);
		}
		//温度下限
		if (ui.boxSecurityTempLow->isChecked())
		{
			step.setProtectTempatureLower(OP_BIG_EQU, securityTempLow);
		}
		//温度上限
		if (ui.boxSecurityTempUp->isChecked())
		{
			step.setProtectTempatureUpper(OP_SMALL_EQU, securityTempUp);
		}
		//延迟时间
		if (ui.boxSecurityDelay->isChecked())
		{
			step.setProtectDelayTime(OP_BIG_EQU, securityDelay * 1000);
		}
		//化成变化率
		if (ui.boxProtectDetal->isChecked())
		{
			step.setProtectDetalVol(OP_BIG_EQU, protectDetalVol);
			step.setProtectDetalVolTime(OP_BIG_EQU, protectDetalVolTime * 1000);
		}
	}

	//更新排序
	stepInfo.step.updateStepLine();

	return true;
}

void StepSettingDialog::updateTable()
{
	m_tableHelper.updateTable(stepInfo);
}

void StepSettingDialog::on_btnAdd_clicked()
{	
	if (stepInfo.step.stepList.size() >= 13)
	{
		QMessageBox::information(this, "", tr("工步数量不能超出13个"));
		return;
	}

	StepEditDialog dlg(this);
	dlg.DeviceString = DeviceString;
	dlg.itemIndex = itemIndex;
	dlg.step.StepType = STEP_TYPE_7;
	dlg.step.StepLine = ui.tableWidget->rowCount();
	if (dlg.exec() != QDialog::Accepted)
		return;

	int idx = stepInfo.step.stepList.size() - 1;	
	stepInfo.step.stepList.insert(idx, dlg.step);

	ui.tableWidget->setCurrentCell(ui.tableWidget->rowCount() - 1, 0);
	updateTable();
}

void StepSettingDialog::on_btnDel_clicked()
{
	int row = ui.tableWidget->currentRow();
	if (row < 0)
		return;
	if (row == ui.tableWidget->rowCount() - 1)
	{
		QMessageBox::information(this,"",tr("结束操作不能删除"));
		return;
	}

	stepInfo.step.stepList.remove(row);
	if (row < ui.tableWidget->currentRow())
		ui.tableWidget->setCurrentCell(row,0);

	updateTable();
}

void StepSettingDialog::on_btnEdit_clicked()
{
	int row = ui.tableWidget->currentRow();
	if (row < 0)
		return;
	if (row == ui.tableWidget->rowCount() - 1)
	{
		QMessageBox::information(this, "", tr("结束操作不能修改"));
		return;
	}

	StepEditDialog dlg(this);
	dlg.DeviceString = DeviceString;
	dlg.itemIndex = itemIndex;
	dlg.step = stepInfo.step.stepList[row];	
	dlg.step.StepLine = row + 1;
	if (dlg.exec() != QDialog::Accepted)
		return;

	stepInfo.step.stepList[row] = dlg.step;
	updateTable();
}

void StepSettingDialog::on_btnUp_clicked()
{
	int row = ui.tableWidget->currentRow();
	if (row > 0 && row != ui.tableWidget->rowCount() - 1)
	{
		qSwap(stepInfo.step.stepList[row], stepInfo.step.stepList[row - 1]);
		
		ui.tableWidget->setCurrentCell(row - 1,0);
		updateTable();
	}
}

void StepSettingDialog::on_btnDown_clicked()
{	
	int row = ui.tableWidget->currentRow();
	if (row >= 0 && row < ui.tableWidget->rowCount() - 2)
	{
		qSwap(stepInfo.step.stepList[row], stepInfo.step.stepList[row + 1]);

		ui.tableWidget->setCurrentCell(row + 1, 0);
		updateTable();
	}
}
void StepSettingDialog::on_btnInit_clicked()
{
	if (QMessageBox::question(this, "", tr("警告，重置将会清除所有数据"), QMessageBox::Yes | QMessageBox::No)
		!= QMessageBox::Yes)
		return;

	stepInfo.step.genDefaultStep();
	initStep();
}

void StepSettingDialog::on_btnSave_clicked()
{
	if (!uiToStep())
		return;

	if (!checkStep())
		return;

	QString filename = QFileDialog::getSaveFileName(this,"","StepInfo.step","*.step");
	if (filename.isEmpty())
		return;

	QFile file(filename);
	if (file.open(QFile::WriteOnly | QFile::Truncate))
	{
		QDataStream s(&file);
		s << stepInfo;
		file.close();
	}
}

void StepSettingDialog::on_btnOpen_clicked()
{
	QString filename = QFileDialog::getOpenFileName(this, "", "","*.step");
	if (filename.isEmpty())
		return;

	QFile file(filename);
	if (file.open(QFile::ReadOnly))
	{
		QDataStream s(&file);
		s >> stepInfo;
		file.close();
	}

	initStep();
}

void StepSettingDialog::on_btnBack_clicked()
{
	
}

void StepSettingDialog::on_btnSet_clicked()
{

}

bool StepSettingDialog::checkParam(QCheckBox *box, QLineEdit *edit, double &var, double low, double upper,bool must)
{
	if (box->isChecked())
	{
		QString title = box->text().trimmed();
		if (!must && title.isEmpty())
			return true;

		bool ok;
		var = edit->text().toDouble(&ok);
		if (!ok)
		{
			QMessageBox::information(this, "", title + tr("格式错误，请检查"));			
		}	
		else if (var < low || var > upper)
		{
			QMessageBox::information(this, "", title + QString::asprintf(qUtf8Printable(tr("取值范围错误，应为:%0.2f - %0.2f")), low,upper));
			ok = false;
		}
		return ok;
	}
	return true;
}

bool StepSettingDialog::checkStep()
{
	int scale = g_project->deviceData(DeviceString)->scale(itemIndex);
	double volt_max = g_project->deviceData(DeviceString)->maxVoltage() * scale;
	double current_max = g_project->deviceData(DeviceString)->maxCurrent() * scale;

	for (int i = 0; i < stepInfo.step.stepList.size(); i++)
	{
		auto &step = stepInfo.step.stepList[i];
		QString pre = "工步" + QString::number(i + 1);
		if (step.isVoltageVaild() && step.Voltage() > volt_max)
		{
			QMessageBox::information(this, "", pre + QString::asprintf(qUtf8Printable(tr("电压应小于%0.2fV")), volt_max));
			return false;
		}
		if (step.isStopVoltageVaild() && step.StopVoltage() > volt_max)
		{
			QMessageBox::information(this, "", pre + QString::asprintf(qUtf8Printable(tr("截止电压应小于%0.2fV")), volt_max));
			return false;
		}
		if (step.isCurrentVaild() && step.Current() > current_max)
		{
			QMessageBox::information(this, "", pre + QString::asprintf(qUtf8Printable(tr("电流应小于%0.2fA")), current_max));
			return false;
		}
		if (step.isStopCurrentVaild() && step.StopCurrent() > current_max)
		{
			QMessageBox::information(this, "", pre + QString::asprintf(qUtf8Printable(tr("截止电流应小于%0.2fA")), current_max));
			return false;
		}
	}

	return true;
}

void StepSettingDialog::on_btnOk_clicked()
{
	if (!uiToStep())
		return;

	if (!checkStep())
		return;

	accept();
}

void StepSettingDialog::on_btnCancel_clicked()
{
	reject();
}

void StepSettingDialog::on_tableWidget_itemPressed(QTableWidgetItem *item)
{
}

void StepSettingDialog::on_tableWidget_itemDoubleClicked(QTableWidgetItem *item)
{
	if (item->row() >= 0)
		on_btnEdit_clicked();
}